import { Inject, Provide } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import axios from 'axios';
import { LakalaTokenEntity } from '../entity/lakala_token';
import { LakalaMerchantEntity } from '../entity/lakala_merchant';
import { LakalaContractEntity } from '../entity/lakala_contract';
import { LakalaConfig } from '../utils/config/lakala';
import { LakalaUtils } from '../utils/lakala';
import moment = require('moment');
import { Utils } from '../../../comm/utils';
import {
  APPLY_URL,
  client_id,
  client_secret,
  LAKALA_BASE_URL,
} from '../constant';
import * as FormData from 'form-data';
import { Context } from '@midwayjs/koa';

/**
 * 拉卡拉商户进件服务
 * 提供token获取、商户进件、合同申请等功能
 */
@Provide()
export class LakalaMerchantService {
  @InjectEntityModel(LakalaTokenEntity)
  tokenModel: Repository<LakalaTokenEntity>;

  @InjectEntityModel(LakalaMerchantEntity)
  merchantModel: Repository<LakalaMerchantEntity>;

  @InjectEntityModel(LakalaContractEntity)
  contractModel: Repository<LakalaContractEntity>;

  @Inject()
  commonUtils: Utils;

  @Inject()
  ctx: Context;

  private readonly config = LakalaConfig.getMerchantConfig();
  private readonly utils = new LakalaUtils();

  /**
   * 获取访问令牌
   * @param appId 应用ID
   * @param appSecret 应用密钥
   * @returns token信息
   */
  async getAccessToken() {
    try {
      // // 检查是否有有效的token
      const existingToken = await this.tokenModel.findOne({
        where: { id: 1 },
      });

      if (existingToken && existingToken.expiresAt > new Date()) {
        return existingToken.accessToken;
      }

      // 构建请求参数
      const requestData = {
        client_id: client_id,
        client_secret: client_secret,
        grant_type: 'client_credentials',
      };

      // 通过formdata发送请求
      const formData = new FormData();
      for (const key in requestData) {
        formData.append(key, requestData[key]);
      }

      // 发送请求
      const response = await axios.post(
        'https://tkapi.lakala.com/auth/oauth/token',
        formData,
        {
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
          },
        }
      );

      const result = response.data;

      console.log('获取到token拉', result);

      /* 获取到的token，将其保存到数据库中，数据库永远只保留一条token */
      if (result?.access_token) {
        /* 保存token */
        await this.tokenModel.update(
          { id: 1 },
          {
            accessToken: result.access_token,
            expiresIn: result.expires_in,
            /* 设置过期时间，返回的单位是秒 */
            expiresAt: new Date(Date.now() + result.expires_in * 1000),
            status: 'active',
          }
        );
      }

      return result?.access_token;
    } catch (error) {
      this.utils.log('获取token失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /**
   * 商户进件申请
   * @param merchantData 商户信息
   * @returns 进件结果
   */
  async applyMerchant(merchantData: any) {
    // 构建请求数据
    const requestData = {
      ...merchantData,
      requestId: this.utils.generateRequestId(),
      timestamp: this.utils.getCurrentTimestamp(),
    };
    try {
      const _token = await this.getAccessToken();

      console.log('requestData', requestData);

      // 发送进件申请
      const response = await axios.post(
        // `${this.config.baseUrl}/api/v3/merchant/apply`,
        'https://htkactvi.lakala.com/registration/merchant',
        requestData,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${_token}`,
          },
        }
      );

      const result = response?.data;

      // 先找一下，是否已经进过件
      this.merchantModel.insert({
        ecNo: merchantData?.contractNo,
        applyParams: JSON.stringify(requestData),
        // 审核中
        status: 2,
        userId: this.ctx.user.id,
        // 进件id
        merchantNo: result?.merchantNo
      });

      return result;
    } catch (error) {
      this.utils.log('商户进件申请失败', error?.response?.data);

      //   // 先找一下，是否已经进过件
      //   this.merchantModel.insert({
      //     ecNo: merchantData?.ecNo,
      //     applyParams: JSON.stringify(requestData),
      //     status: 0,
      //   });

      return {
        success: false,
        error: error?.response?.data || '网络请求失败',
      };
    }
  }

  /**
   * 合同申请
   * @param contractData 合同信息
   * * @param applicationData 进见内容
   * @param userId 用户ID
   * @returns 合同申请结果
   */
  async applyContract(contractData: any, userId: string) {
    try {
      /* 先判断当前用户是否有合同记录 */
      // const existingContract = await this.contractModel.findOne({
      //   where: { userId },
      // });

      // if (existingContract) {
      //   return {
      //     success: false,
      //     msg: '当前用户已经申请过合同',
      //     data: existingContract,
      //     code: 1000
      //   };
      // }

      // 平台编号+14位年月日时（24小时制）分秒+8位的随机数（同一接入机构不重复）
      const order_no = `${moment().format('YYYYMMDDHHmmss')}${Math.floor(
        Math.random() * 100000000
      )}`;

      // 获取当前时间的年份
      const year = moment().format('YYYY');

      // 获取当前时间的月份
      const month = moment().format('MM');

      // 当前时间的日期
      const day = moment().format('DD');

      const _body = {
        req_data: {
          order_no: order_no,
          // 测试环境串1
          org_id: 984459,
          // 固定
          ec_type_code: 'EC008',
          // 法人/经营者证件类型
          cert_type: 'RESIDENT_ID',
          // 法人/经营者姓名
          cert_name: contractData?.larName,
          // 法人/经营者证件号码
          cert_no: contractData?.larIdCard,
          // 签约手机号
          mobile: contractData?.contactMobile,
          // 57 对公、 58 对私，这里固定
          acct_type_code: 58,
          // 企业/经营者结算卡号
          acct_no: contractData?.accountNo,
          // 企业/经营者结算卡名称
          acct_name: contractData?.larName,
          // 电子合同内容参数集合
          ec_content_parameters: JSON.stringify({
            A1: contractData?.larName,

            // 外卡手续费
            A15: "1.5",
            A16: '2.0',
            A17: '1.5',
            A18: '2.0',
            A20: "3.5",
            A22: "3.5",
            A25: "1.5",
            A26: "3.5",
            // 收单手续费
            A7: "0.5",
            A8: "20",
            A10: "0.6",

            // 终端信息
            A89: "60.0",
            A90: "线上",

            A96: 2,
            // 支付宝收单手续费
            A29: "1",
            // 微信搜单手续费
            A30: "1",
            B1: year,
            B2: month,
            B8: contractData?.larName,
            B9: "电玩店",
            B20: contractData?.accountNo,
            B24: contractData?.larName,
            B25: contractData?.larIdCard,
            B26: contractData?.contactMobile,

            // 授权书，银行
            D2: `${year}年${month}月${day}日`,
            // 授权胡（数据处理方）
            D4: "深圳市润银信数字科技有限公司",
            D5: "17302644218",
            D7: `${year}年${month}月${day}日`,

            // 授权书，外卡业务
            D9:  `${year}年${month}月${day}日`,
            D11:  `${year}年${month}月${day}日`,
            D12:  `${year}年${month}月${day}日`

          }),
          // 企业/经营者结算开户行号
          openning_bank_code: contractData?.openningBankCode,
          //  	企业/经营者结算开户行名称
          openning_bank_name: contractData?.openningBankName,
          // 	备注说明
          remark: '测试',
          version: '1.0',
          // 回调地址
          ret_url:
            'https://ryxkeji.com/api/app/lakala/merchant/contract/callback',
        },
      };
      // 发送合同申请
      const response = await axios.post(APPLY_URL, _body, {
        headers: {
          'Content-Type': 'application/json',
          Accept: 'application/json',
          Authorization: this.commonUtils.createAuthorization(_body),
        },
      });

      const result = response.data;

      console.log('申请合同回调信息', { result, _body });

      // 如果申请合同成功，把申请结果保存到数据库中
      if (result.code === '000000') {
        await this.contractModel.save({
          // 电子签约申请受理编号
          ecApplyId: result.resp_data.ec_apply_id,
          status: 0,
          userId,
          orderNo: order_no,
          signUrl: result.resp_data.result_url,
          // applicationData: JSON.stringify(applicationData),
        });

        return result;
      } else {
        // return result;
        return {
          success: false,
          error: result || '网络请求失败',
          msg: result?.msg,
        };

      }
    } catch (error) {
      this.utils.log('合同申请失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /**
   * 查询商户审核状态
   * @param merchantNo 商户号
   * @param accessToken 访问令牌
   * @returns 审核状态
   */
  // async queryMerchantStatus(merchantNo: string, accessToken: string) {
  //   try {
  //     const response = await axios.get(
  //       `${this.config.baseUrl}/api/v3/merchant/status/${merchantNo}`,
  //       {
  //         headers: {
  //           Authorization: `Bearer ${accessToken}`,
  //           'User-Agent': 'Lakala-Merchant-SDK',
  //         },
  //         timeout: this.config.timeout,
  //       }
  //     );

  //     const result = response.data;

  //     if (result.code === '000000') {
  //       // 更新本地商户状态
  //       await this.merchantModel.update(
  //         { lakalaMerchantNo: merchantNo },
  //         {
  //           status: result.data.status,
  //           auditTime: result.data.auditTime
  //             ? new Date(result.data.auditTime)
  //             : null,
  //           auditRemark: result.data.auditRemark,
  //         }
  //       );

  //       return {
  //         success: true,
  //         data: result.data,
  //       };
  //     } else {
  //       return {
  //         success: false,
  //         error: result.message || '查询商户状态失败',
  //         code: result.code,
  //       };
  //     }
  //   } catch (error) {
  //     this.utils.log('查询商户状态失败', error);
  //     return {
  //       success: false,
  //       error: error.message || '网络请求失败',
  //     };
  //   }
  // }

  /**
   * 查询合同状态
   * @param contractNo 合同号
   * @param accessToken 访问令牌
   * @returns 合同状态
   */
  async queryContractStatus(contractNo: string, accessToken: string) {
    try {
      const response = await axios.get(
        `${this.config.baseUrl}/api/v3/contract/status/${contractNo}`,
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
            'User-Agent': 'Lakala-Merchant-SDK',
          },
          timeout: this.config.timeout,
        }
      );

      const result = response.data;

      if (result.code === '000000') {
        // 更新本地合同状态
        await this.contractModel.update(
          { ecApplyId: contractNo },
          {
            status: result.data.status,
          }
        );

        return {
          success: true,
          data: result.data,
        };
      } else {
        return {
          success: false,
          error: result.message || '查询合同状态失败',
          code: result.code,
        };
      }
    } catch (error) {
      this.utils.log('查询合同状态失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /**
   * 验证商户进件参数
   */
  private validateMerchantParams(data: any): boolean {
    const required = [
      'merchantNo',
      'merchantName',
      'merchantType',
      'businessLicense',
      'legalPerson',
      'contactPhone',
      'contactEmail',
      'bankAccount',
      'bankName',
    ];

    return required.every(field => data[field]);
  }

  /**
   * 验证合同申请参数
   */
  private validateContractParams(data: any): boolean {
    const required = [
      'merchantNo',
      'contractType',
      'contractTemplate',
      'signType',
      'signerName',
      'signerPhone',
      'signerIdCard',
    ];

    return required.every(field => data[field]);
  }

  /**
   * 文件上传
   * @param files 文件数据
   * @param imgType 文件类型
   * @param accessToken 访问令牌
   * @param sourcechnl 来源渠道
   * @returns 上传结果
   */
  async uploadFile(
    files: any[],
    imgType: string,
    accessToken: string,
    sourcechnl: string
  ) {
    try {
      console.log('files', files);

      const formData = new FormData();

      formData.append('file', files?.[0].data, {
        filename: files?.[0]?.filename,
      });

      formData.append('imgType', imgType);
      formData.append('sourcechnl', sourcechnl);
      formData.append('isOcr', 'false');

      console.log('formData=====>', formData);

      const response = await axios.post(
        'https://htkactvi.lakala.com/registration/file/upload',
        formData,
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
            ...formData.getHeaders(),
          },
          timeout: this.config.uploadTimeout || 30000,
        }
      );

      const result = response.data;

      console.log('上传结果', result);

      if (result.code === '000000') {
        return {
          success: true,
          data: {
            fileId: result.data.fileId,
            fileUrl: result.data.fileUrl,
            fileName: result.data.fileName,
          },
        };
      } else {
        return {
          success: false,
          error: result.message || '文件上传失败',
          code: result.code,
        };
      }
    } catch (error) {
      this.utils.log('文件上传失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /**
   * 文件下载
   * @param fileId 文件ID
   * @param accessToken 访问令牌
   * @returns 文件流
   */
  async downloadFile(fileId: string, accessToken: string) {
    try {
      const response = await axios.get(
        `${this.config.baseUrl}/api/v3/file/download/${fileId}`,
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
            'User-Agent': 'Lakala-Merchant-SDK',
          },
          responseType: 'stream',
          timeout: this.config.downloadTimeout || 60000,
        }
      );

      return {
        success: true,
        data: response.data,
        headers: response.headers,
      };
    } catch (error) {
      this.utils.log('文件下载失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /* 获取银行列表 */
  async getBankList(query: any) {
    try {
      const _token = await this.getAccessToken();

      const response = await axios.get(
        // `https://htkactvi.lakala.com/registration/bank?areaCode=${query?.parentCode}`,
        `https://htkactvi.lakala.com/registration/bank?areaCode=${query}`,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${_token}`,
          },
        }
      );

      console.log('responseresponseresponseresponseresponse=>', response.data);

      const result = response.data;
      return result;
    } catch (error) {
      this.utils.log('获取银行列表失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /* 获取地区 */
  async getAreaList(query: any) {
    try {
      const _token = await this.getAccessToken();

      console.log('queryqueryqueryquery', query);

      const response = await axios.get(
        `https://htkactvi.lakala.com/registration/organization/${query || 1}`,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${_token}`,
          },
        }
      );

      const result = response.data;

      return result;
    } catch (error) {
      this.utils.log('获取银行列表失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }

  /* 银行地区 */
  async getBankAreaList(query: any) {
    try {
      const _token = await this.getAccessToken();

      const response = await axios.get(
        `https://htkactvi.lakala.com/registration/organization/bank/${query || 1
        }`,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${_token}`,
          },
        }
      );

      const result = response.data;
      console.log('resultresultresult', result);

      return result;
    } catch (error) {
      this.utils.log('获取银行列表失败', error);
      return {
        success: false,
        error: error.message || '网络请求失败',
      };
    }
  }
}
